package cn.quang.search.admin.service.impl;

import cn.quang.search.admin.entity.po.*;
import cn.quang.search.admin.mapper.*;
import cn.quang.search.admin.service.ISearchConfigChangeService;
import cn.quang.search.common.utils.FastJsonUtils;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class SearchConfigChangeService implements ISearchConfigChangeService {
    private static final int ESB_SUBJECT_ID = 113666;

    private final EntityLogicTableRelationMapper entityLogicTableRelationMapper;
    private final EntityTableMapper entityTableMapper;
    private final SearchSceneMapper searchSceneMapper;
    private final SearchSceneConfigMapper searchSceneConfigMapper;
    private final SearchSceneInnerFetcherConfigMapper searchSceneInnerFetcherConfigMapper;
    private final SearchConditionTableRelationMapper searchConditionTableRelationMapper;
    private final SearchResultFetcherTableRelationMapper searchResultFetcherTableRelationMapper;
    private final EntityLogicTableFieldDicMapper entityLogicTableFieldDicMapper;

    /**
     * 根据数据源ID查找关联场景
     */
    @Override
    public void triggerByDataSource(long dataSourceId) {
        try {
            Set<Long> logicTableIds = Sets.newHashSet();
            // 查询数据源关联的逻辑表
            List<EntityTable> entityTables = entityTableMapper.selectByDataSourceId(dataSourceId);
            if(CollectionUtils.isNotEmpty(entityTables)) {
                List<Long> tableIds = entityTables.stream().map(EntityTable::getId).distinct().collect(Collectors.toList());

                if(CollectionUtils.isNotEmpty(tableIds)) {
                    for (Long tableId : tableIds) {
                        List<EntityLogicTableRelation> logicTableRelations = entityLogicTableRelationMapper.selectByTableId(tableId);
                        for (EntityLogicTableRelation logicTableRelation : logicTableRelations) {
                            logicTableIds.add(logicTableRelation.getLogicTableId());
                        }
                    }
                }
            }
            // 最终通过逻辑表触发场景同步
            if(CollectionUtils.isNotEmpty(logicTableIds)) {
                for (Long logicTableId : logicTableIds) {
                    triggerByLogicTable(logicTableId);
                }
            }
        } catch (Exception e) {
            log.error(String.format("数据源(ID=%s)变更触发推送异常", dataSourceId), e);
        }
    }

    /**
     * 根据通用字典推送
     */
    @Override
    public void triggerByFieldDic(long fieldDicId) {
        try {
            Set<Long> logicTableIds = Sets.newHashSet();
            List<EntityLogicTableFieldDic> entityLogicTableFieldDices = entityLogicTableFieldDicMapper.selectByFieldDicId(fieldDicId);
            if(CollectionUtils.isNotEmpty(entityLogicTableFieldDices)) {
                for (EntityLogicTableFieldDic entityLogicTableFieldDic : entityLogicTableFieldDices) {
                    logicTableIds.add(entityLogicTableFieldDic.getLogicTableId());
                }
            }

            // 最终通过逻辑表触发场景同步
            if(CollectionUtils.isNotEmpty(logicTableIds)) {
                for (Long logicTableId : logicTableIds) {
                    triggerByLogicTable(logicTableId);
                }
            }
        } catch (Exception e) {
            log.error(String.format("通用字典(ID=%s)变更触发推送异常", fieldDicId), e);
        }
    }

    /**
     * 根据逻辑表推送
     */
    @Override
    public void triggerByLogicTable(long logicTableId) {
        try {
            Set<Long> sceneIds = Sets.newHashSet();
            List<SearchSceneConfig> searchSceneConfigs = searchSceneConfigMapper.selectByLogicTableId(logicTableId);
            if(CollectionUtils.isNotEmpty(searchSceneConfigs)) {
                for (SearchSceneConfig searchSceneConfig : searchSceneConfigs) {
                    sceneIds.add(searchSceneConfig.getSceneId());
                }
            }

            // 最终通过逻辑表触发场景同步
            if(CollectionUtils.isNotEmpty(sceneIds)) {
                for (Long sceneId : sceneIds) {
                    triggerBySceneId(sceneId);
                }
            }
        } catch (Exception e) {
            log.error(String.format("逻辑表(ID=%s)变更触发推送异常", logicTableId), e);
        }
    }

    /**
     * 查询关联该条件的逻辑表
     */
    @Override
    public void triggerByCondition(long conditionId) {
        try {
            Set<Long> logicTableIds = Sets.newHashSet();
            List<SearchConditionTableRelation> relations = searchConditionTableRelationMapper.selectByConditionId(conditionId);
            if(CollectionUtils.isNotEmpty(relations)) {
                for (SearchConditionTableRelation relation : relations) {
                    logicTableIds.add(relation.getLogicTableId());
                }
            }

            // 最终通过逻辑表触发场景同步
            if(CollectionUtils.isNotEmpty(logicTableIds)) {
                for (Long logicTableId : logicTableIds) {
                    triggerByLogicTable(logicTableId);
                }
            }
        } catch (Exception e) {
            log.error(String.format("查询条件(ID=%s)变更触发推送异常", conditionId), e);
        }
    }

    /**
     * 查询取数器关联场景
     */
    @Override
    public void triggerByResultFetcher(long fetcherId) {
        try {
            Set<Long> logicTableIds = Sets.newHashSet();
            List<SearchResultFetcherTableRelation> relations = searchResultFetcherTableRelationMapper.selectByFetcherId(fetcherId);
            if(CollectionUtils.isNotEmpty(relations)) {
                for (SearchResultFetcherTableRelation relation : relations) {
                    logicTableIds.add(relation.getLogicTableId());
                }
            }

            // 最终通过逻辑表触发场景同步
            if(CollectionUtils.isNotEmpty(logicTableIds)) {
                for (Long logicTableId : logicTableIds) {
                    triggerByLogicTable(logicTableId);
                }
            }
        } catch (Exception e) {
            log.error(String.format("自定义取数器(ID=%s)变更触发推送异常", fetcherId), e);
        }
    }

    /**
     * 内置取数器
     */
    @Override
    public void triggerByInnerFetcher(long innerFetcherId) {
        try {
            Set<Long> sceneIds = Sets.newHashSet();
            List<SearchSceneInnerFetcherConfig> configs = searchSceneInnerFetcherConfigMapper.selectByInnerFetcherId(innerFetcherId);
            if(CollectionUtils.isNotEmpty(configs)) {
                for (SearchSceneInnerFetcherConfig config : configs) {
                    sceneIds.add(config.getSceneId());
                }
            }

            // 最终通过逻辑表触发场景同步
            if(CollectionUtils.isNotEmpty(sceneIds)) {
                for (Long sceneId : sceneIds) {
                    triggerBySceneId(sceneId);
                }
            }
        } catch (Exception e) {
            log.error(String.format("内置取数器(ID=%s)变更触发推送异常", innerFetcherId), e);
        }
    }

    /**
     * 场景
     */
    @Override
    public void triggerBySceneId(long sceneId) {
        try {
            SearchScene searchScene = searchSceneMapper.selectById(sceneId);
            if(searchScene == null) {
                log.error(String.format("场景(ID=%s)不存在，无法推送", sceneId));
                return;
            }
            sendChangeEvent(searchScene.getCode());
        } catch (Exception e) {
            log.error(String.format("场景(ID=%s)变更触发推送异常", sceneId), e);
        }
    }

    private void sendChangeEvent(String sceneCode) {
        try {
            Map<String, Object> event = Maps.newHashMap();
            event.put("sceneCode", sceneCode);
            event.put("description", "场景或其关联配置发生变更");

//            ESBService.send(ESB_SUBJECT_ID, FastJsonUtils.beanToJson(event));
        } catch (Exception e) {
            log.error(String.format("场景(CODE=%s)配置读取异常，无法推送", sceneCode), e);
        }
    }
}
